package com.yst.webplugin.util;

import com.yst.web.utils.BeanUtils;
import com.yst.webplugin.exception.ExceptionParam;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.io.Serializable;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class ParamUtils {

    private static final ValidatorFactory validatorFactory;
    private static final Validator validator;

    /**
     * empty object
     */
    public static final EmptyObject emptyObject;

    static {
        emptyObject=new EmptyObject();
        validatorFactory= Validation.buildDefaultValidatorFactory();
        validator=validatorFactory.getValidator();
    }

    static class EmptyObject implements Serializable{
        //empty body
    }

    /**
     * Check parameter with output error path
     * @param params parameter
     * @param validClass class of valid config
     * @param showPath output path
     * @param groups class of check group
     * @throws Exception
     */
    public static void checkParams(Object params, Class<?> validClass, Boolean showPath, Class<?>...groups) throws Exception {

        if (validClass== Serializable.class) return;

        if (Objects.isNull(params)) throw new ExceptionParam("params is null");

        Object validObj=params;
        if (params instanceof Map){
            Map<String,Object> mapParams=(Map<String, Object>) params;
            validObj=validClass.newInstance();
            BeanUtils.mapToBean(mapParams,validClass);
        }

        Set<ConstraintViolation<Object>> constraintViolations;
        if (Objects.nonNull(groups)) {
            constraintViolations =validator.validate(validObj, groups);
        }
        else
        {
            constraintViolations=validator.validate(validObj);
        }

        if (constraintViolations.isEmpty()) return;
        throw new ExceptionParam(constraintViolations.stream().findFirst().get().getMessage());
    }

    /**
     * Check parameter
     * @param params parameter
     * @param validClass class of valid config
     * @param groups class of check group
     * @throws ExceptionParam
     */
    public static void checkParams(Object params, Class<?> validClass, Class<?>...groups) throws Exception {
        checkParams(params,validClass,false,groups);
    }
}
